package com.relatev.minecraft.TRMobAPI;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.metadata.Metadatable;
import org.bukkit.scheduler.BukkitTask;

public class TRMobManager {

    private HashMap<String, TRMob> TRMobDictionary = new HashMap<>();

    /**
     * TRMobAPI支持热拔插，这将彻底卸载一类怪物 但已经被生成的怪物不会被清理 若要清理所有已生成的此类怪物，
     * 请手动遍历getLivingMobs进行清理 若不清理怪物，在下次该类怪物装载后 怪物会恢复为该类的特性
     *
     * @param tm 要删除的怪物类
     */
    public void unloadMob(TRMob tm) {
        TRMobAPI.getAPI().getLogger().info("开始卸载生物 " + tm.ID);
        try {
            Field TRMobTasksField = ReflectionUtils.getDeclaredFieldIncludingParents(tm.getClass(), "Tasks");
            TRMobTasksField.setAccessible(true);
            ArrayList<BukkitTask> mobtasks = (ArrayList<BukkitTask>) TRMobTasksField.get(tm);
            for (BukkitTask task : mobtasks) {
                task.cancel();
            }
            for (TRAbility tra : tm.Abilities) {
                tra.onUnload();
                Field abtasksfield = ReflectionUtils.getDeclaredFieldIncludingParents(tra.getClass(), "Tasks");
                abtasksfield.setAccessible(true);
                ArrayList<BukkitTask> abtasks = (ArrayList<BukkitTask>) abtasksfield.get(tra);
                for (BukkitTask task : abtasks) {
                    task.cancel();
                }
            }
            for (Entity ent : tm.getLivingMobs()) {
                ent.remove();
            }
            tm.onUnload();
            Field TRMobsField = ReflectionUtils.getDeclaredFieldIncludingParents(TRMob.class, "TRMobs");
            TRMobsField.setAccessible(true);
            ArrayList<TRMob> mobs = (ArrayList<TRMob>) TRMobsField.get(TRMob.class);
            mobs.remove(tm);
            TRMobDictionary.remove(tm.ID);
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException ex) {
            Logger.getLogger(TRMobManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * 将卸载一切被装载的怪物类，一般不需要开发者调用
     */
    public void unloadAllMob(){
        for(TRMob trm:getTRMobs()){
            unloadMob(trm);
        }
    }

    /**
     * TRMobAPI支持热拔插，这将装载一类怪物 任何已在世界上被生成的怪物会重新赋予该类特性
     *
     * @param tm 要装载的怪物类
     */
    public void loadMob(TRMob tm) {
        try {
            Field TRMobsField = TRMob.class.getDeclaredField("TRMobs");
            TRMobsField.setAccessible(true);
            ArrayList<TRMob> TRMobs = (ArrayList<TRMob>) TRMobsField.get(TRMob.class);
            if (TRMobs.contains(tm)) {
                TRMobAPI.getAPI().getLogger().warning("注意！生物 " + tm.ID + " 有相同ID的怪物已加载过，将用新加载的生物替换旧有生物！");
                TRMobAPI.getAPI().getTRMobManager().unloadMob(tm);
            }

            if (tm instanceof TRMobConfigurable) {
                TRMobAPI.getAPI().getLogger().info("正在读取生物 " + tm.ID + " 的Json配置文件");
                TRMob configmob = TRMobAPI.getAPI().getTRConfigManager().getTRMobByConfig(tm);
                for (Field field : ReflectionUtils.getDeclaredFieldsIncludingParents(tm.getClass())) {
                    field.setAccessible(true);
                    if (field.isAnnotationPresent(TRFieldConfigurable.class)) {
                        field.set(tm, field.get(configmob));
                    }
                }
            }

            TRMobAPI.getAPI().getLogger().info("开始加载生物 " + tm.ID);

            tm.onLoad();
            for (TRAbility tra : tm.Abilities) {
                Field parenttrmfield = tra.getClass().getField("ParentTRMob");
                parenttrmfield.setAccessible(true);
                parenttrmfield.set(tra, tm);
                tra.onLoad();
            }
            Field MobsField = TRMob.class.getDeclaredField("Mobs");
            MobsField.setAccessible(true);
            ArrayList<LivingEntity> Mobs = (ArrayList<LivingEntity>) MobsField.get(tm);
            tm.loginBukkitTask(Bukkit.getScheduler().runTaskTimer(TRMobAPI.getAPI(), new Runnable() {
                @Override
                public void run() {
                    Iterator<LivingEntity> it = Mobs.iterator();
                    while (it.hasNext()) {
                        if (it.next().isValid() == false) {
                            it.remove();
                        }
                    }
                }
            }, 20, 20));
            TRMobs.add(tm);
            TRMobDictionary.put(tm.ID, tm);
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
            Logger.getLogger(TRMobManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * 获取所有被装载的怪物类
     *
     * @return 获取的结果
     */
    public List<TRMob> getTRMobs() {
        return TRMob.getTRMobs();
    }

    /**
     * 通过指定ID获取怪物类 请填ID全名，不支持模糊匹配 要进行模糊匹配，请使用fuzzyRecognizeTRMob
     *
     * @param id 怪物的全ID
     * @return 获取的结果
     */
    public TRMob getTRMob(String id) {
        return TRMobDictionary.get(id);
    }

    /**
     * 通过指定实体获取怪物类 若该实体不属于任何怪物类 或属于的怪物类已被卸载 将返回null
     *
     * @param mda 实体
     * @return 获取的结果
     */
    public TRMob getTRMob(Metadatable mda) {
        if (mda.hasMetadata("TRMob") && mda.getMetadata("TRMob").isEmpty() == false) {
            return TRMobDictionary.get(mda.getMetadata("TRMob").get(0).asString());
        }
        return null;
    }

    /**
     * 通过一段字符串模糊匹配搜索怪物类 但请注意，该方法性能较差 只建议在命令或必要情况下使用此方法 若找不到，将返回null
     *
     * @param str 模糊匹配的字符串
     * @return 获取的结果
     */
    public TRMob fuzzyRecognizeTRMob(String str) {
        if (TRMobDictionary.containsKey(str)) {
            return TRMobDictionary.get(str);
        }
        for (TRMob trm : TRMob.getTRMobs()) {
            if (trm.ID.toLowerCase().contains(str.toLowerCase())) {
                return trm;
            }
        }
        return null;
    }
}
